/**
 * Vitest 测试环境设置
 */

import { vi } from 'vitest'

// Mock Element Plus 全局组件
global.ElMessage = {
  success: vi.fn(),
  error: vi.fn(),
  warning: vi.fn(),
  info: vi.fn()
}

global.ElMessageBox = {
  confirm: vi.fn().mockResolvedValue('confirm'),
  alert: vi.fn().mockResolvedValue('confirm'),
  prompt: vi.fn().mockResolvedValue({ value: 'test' })
}

global.ElNotification = {
  success: vi.fn(),
  error: vi.fn(),
  warning: vi.fn(),
  info: vi.fn()
}

// Mock DOM APIs
Object.defineProperty(window, 'matchMedia', {
  writable: true,
  value: vi.fn().mockImplementation(query => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: vi.fn(),
    removeListener: vi.fn(),
    addEventListener: vi.fn(),
    removeEventListener: vi.fn(),
    dispatchEvent: vi.fn()
  }))
})

// Mock ResizeObserver
global.ResizeObserver = vi.fn().mockImplementation(() => ({
  observe: vi.fn(),
  unobserve: vi.fn(),
  disconnect: vi.fn()
}))

// Mock IntersectionObserver
global.IntersectionObserver = vi.fn().mockImplementation(() => ({
  observe: vi.fn(),
  unobserve: vi.fn(),
  disconnect: vi.fn()
}))

// Mock localStorage
const localStorageMock = {
  getItem: vi.fn(),
  setItem: vi.fn(),
  removeItem: vi.fn(),
  clear: vi.fn()
}
global.localStorage = localStorageMock

// Mock sessionStorage
const sessionStorageMock = {
  getItem: vi.fn(),
  setItem: vi.fn(),
  removeItem: vi.fn(),
  clear: vi.fn()
}
global.sessionStorage = sessionStorageMock

// Mock URL.createObjectURL
global.URL.createObjectURL = vi.fn(() => 'mocked-url')
global.URL.revokeObjectURL = vi.fn()

// Mock File API
global.File = class MockFile {
  constructor(bits, name, options = {}) {
    this.bits = bits
    this.name = name
    this.size = bits.reduce((acc, bit) => acc + bit.length, 0)
    this.type = options.type || ''
    this.lastModified = options.lastModified || Date.now()
  }
}

global.FileReader = class MockFileReader {
  constructor() {
    this.readyState = 0
    this.result = null
    this.error = null
    this.onload = null
    this.onerror = null
    this.onabort = null
  }

  readAsText(file) {
    setTimeout(() => {
      this.readyState = 2
      this.result = 'mocked file content'
      if (this.onload) this.onload({ target: this })
    }, 0)
  }

  readAsDataURL(file) {
    setTimeout(() => {
      this.readyState = 2
      this.result = 'data:text/plain;base64,bW9ja2VkIGZpbGUgY29udGVudA=='
      if (this.onload) this.onload({ target: this })
    }, 0)
  }
}

// Mock Blob
global.Blob = class MockBlob {
  constructor(parts = [], options = {}) {
    this.parts = parts
    this.size = parts.reduce((acc, part) => acc + part.length, 0)
    this.type = options.type || ''
  }

  text() {
    return Promise.resolve(this.parts.join(''))
  }

  arrayBuffer() {
    return Promise.resolve(new ArrayBuffer(this.size))
  }
}

// Mock Canvas API
HTMLCanvasElement.prototype.getContext = vi.fn(() => ({
  fillRect: vi.fn(),
  clearRect: vi.fn(),
  getImageData: vi.fn(() => ({ data: new Array(4) })),
  putImageData: vi.fn(),
  createImageData: vi.fn(() => ({ data: new Array(4) })),
  setTransform: vi.fn(),
  drawImage: vi.fn(),
  save: vi.fn(),
  fillText: vi.fn(),
  restore: vi.fn(),
  beginPath: vi.fn(),
  moveTo: vi.fn(),
  lineTo: vi.fn(),
  closePath: vi.fn(),
  stroke: vi.fn(),
  translate: vi.fn(),
  scale: vi.fn(),
  rotate: vi.fn(),
  arc: vi.fn(),
  fill: vi.fn(),
  measureText: vi.fn(() => ({ width: 0 })),
  transform: vi.fn(),
  rect: vi.fn(),
  clip: vi.fn()
}))

HTMLCanvasElement.prototype.toDataURL = vi.fn(() => '')
HTMLCanvasElement.prototype.toBlob = vi.fn(callback => {
  callback(new Blob(['mocked'], { type: 'image/png' }))
})

// Mock Image
global.Image = class MockImage {
  constructor() {
    this.onload = null
    this.onerror = null
    this.src = ''
    this.width = 0
    this.height = 0
  }

  set src(value) {
    this._src = value
    setTimeout(() => {
      this.width = 100
      this.height = 100
      if (this.onload) this.onload()
    }, 0)
  }

  get src() {
    return this._src
  }
}

// Mock print function
global.print = vi.fn()

// Mock jQuery (基础版本)
global.jQuery = global.$ = {
  fn: {
    xemrEditor: vi.fn(() => ({
      getContent: vi.fn().mockReturnValue('<p>测试内容</p>'),
      setContent: vi.fn(),
      insertContent: vi.fn(),
      clear: vi.fn(),
      destroy: vi.fn()
    }))
  },
  noConflict: vi.fn(() => global.jQuery),
  ready: vi.fn(fn => fn()),
  extend: vi.fn(),
  each: vi.fn(),
  ajax: vi.fn().mockResolvedValue({ success: true })
}

// Mock window.open
global.open = vi.fn()

// Mock navigator
Object.defineProperty(navigator, 'clipboard', {
  value: {
    writeText: vi.fn().mockResolvedValue(),
    readText: vi.fn().mockResolvedValue('mocked clipboard text')
  }
})

// Mock crypto
Object.defineProperty(global, 'crypto', {
  value: {
    randomUUID: vi.fn(() => 'mocked-uuid-1234-5678-9012')
  }
})
